package org.muninn.niagara.math;

import javax.baja.status.BStatusNumeric;
import javax.baja.sys.BComponent;
import javax.baja.sys.BDynamicEnum;
import javax.baja.sys.BEnumRange;
import javax.baja.sys.BIcon;
import javax.baja.sys.Context;
import javax.baja.sys.Flags;
import javax.baja.sys.Property;
import javax.baja.sys.Sys;
import javax.baja.sys.Type;

public class BMultiReset extends BComponent
{
  /** Total number of reset schemes **/
  public static final Property total = newProperty(Flags.SUMMARY, 3);
  public void setTotal(int v) { setInt(total, v, null); }
  public int getTotal() { return getInt(total); }
  
  /** Dynamically updated to allow selection of any of the schemes **/
  public static final Property select = newProperty(Flags.SUMMARY, BDynamicEnum.make(0));
  public void setSelect(BDynamicEnum v) { set(select, v, null); }
  public BDynamicEnum getSelect() { return (BDynamicEnum) get(select); }
  
  /** Numeric input to be converted **/
  public static final Property in = newProperty(Flags.SUMMARY, new BStatusNumeric());
  public void setIn(BStatusNumeric v) { set(in, v, null); }
  public BStatusNumeric getIn() { return (BStatusNumeric) get(in); }
  
  /** Converted value of <code>in</code> **/
  public static final Property out = newProperty(Flags.SUMMARY|Flags.READONLY, new BStatusNumeric());
  public void setOut(BStatusNumeric v) { set(out, v); }
  public BStatusNumeric getOut() { return (BStatusNumeric) get(out); }
  
  private static int tot;
  private static double input;
  
  public void started() { refresh(); }
  
  public void changed(Property p, Context cx)
  {
    if (!isRunning())
      return;
    
    if (p.equals(total))
      refresh();
    
    else if (!p.equals(out))
      execute();
  }
  
  public void execute()
  {
    int sel = getSelect().getOrdinal();
    
    double result = reset(((BStatusNumeric) get("Input" + (sel+1) + "Low")).getValue(),
                          ((BStatusNumeric) get("Input" + (sel+1) + "High")).getValue(),
                          ((BStatusNumeric) get("Output" + (sel+1) + "Low")).getValue(),
                          ((BStatusNumeric) get("Output" + (sel+1) + "High")).getValue());
    
    getOut().setValue(result);
  }
  
  public void refresh()
  {
    tot = getTotal();
    this.removeAll();
    
    int[] ordinals = new int[tot];
    String[] vals = new String[tot];
    
    for (int i = 0; i < tot; i++)
    {
      ordinals[i] = i;
      vals[i] = "Scheme" + (i+1);
    }
    
    for (int i = 0; i < tot; i++)
    {
      this.add("Input" + (i+1) + "Low", new BStatusNumeric(0), Flags.SUMMARY);
      this.add("Input" + (i+1) + "High", new BStatusNumeric(0), Flags.SUMMARY);
      this.add("Output" + (i+1) + "Low", new BStatusNumeric(0), Flags.SUMMARY);
      this.add("Output" + (i+1) + "High", new BStatusNumeric(0), Flags.SUMMARY);
    }
    
    setSelect(BDynamicEnum.make(0, BEnumRange.make(ordinals, vals)));
    getOut().setValue(0);
  }
  
  public double reset(double inLow, double inHigh, double outLow, double outHigh)
  {
    input = ((BStatusNumeric) get(in)).getValue();
    
    if (input <= inLow)
      return outLow;
    if (input >= inHigh)
      return outHigh;
      
    return (outHigh - outLow) / (inHigh - inLow) * (input - inLow) + outLow;
  }
  
  public BIcon getIcon() { return icon; }
  private static final BIcon icon = BIcon.make("local:|module://muninn/org/muninn/niagara/graphics/MuninnGroup.PNG");

  public static final Type TYPE = Sys.loadType(BMultiReset.class);
  public Type getType() { return TYPE; }
}
